package project;

import java.util.LinkedList;

public class lottery {

	private int clk ;
	private LinkedList <process> allProcesses;
	private LinkedList <user> users;
	private boolean inQuantum = false;
	
	/**
	 * Constructor for the lottery scheduler
	 * @param clk
	 */

	public lottery(int clk)
	{
		super();
		this.clk = clk;
		this.allProcesses = new LinkedList <process> ();
		this.users = new LinkedList <user>();
	}

	/**
	 * main method to start the system
	 * @param args
	 */
	public static void  main (String args[])
	{
		lottery l = new lottery(0);
		
		LinkedList<process> user1List = new LinkedList <process> ();
		LinkedList<process> user2List = new LinkedList <process> ();
		
		process p1 = new process("p1",0,4,"user1");
		user1List.add(p1);
		
		process p2 =  new process("p2",5,2,"user2");
		user2List.add(p2);
		process p3 =  new process("p3",5,2,"user2");
		user2List.add(p3);
		
		user user1 = new user ("user1",user1List,2);
		user user2 = new user ("user2",user2List,3);
		
		
		l.getUsers().addLast(user1);
		l.getUsers().addLast(user2);
		
		l.addingProcesses();		
	}
	
	/**
	 * adds the processes arriving at an instant
	 * according to the arrival time
	 */
	public void addingProcesses()
	{
		for (int i = 0; i < getUsers().size(); i++) 
		{
			for (int j = 0; j < getUsers().get(i).getUserProcesses().size(); j++)
			{
				for (int k = 1; k <= users.get(i).getUserPriority(); k++) 
				{
					if (getUsers().get(i).getUserProcesses().get(j)
							.getArrival_time() == getClk()) 
					{
						getAllProcesses().addLast(
								getUsers().get(i).getUserProcesses().get(j));
						System.out.println("adding a process "
								+ getUsers().get(i).getUserProcesses().get(j)
										.getName());
					}
				}
			}
		}
		removingRunningProcesses();
		removingEmptyUsers();
		if(!inQuantum)
		{
		run();
		}
	}
	
	/**
	 * removes the processes that are running form the list
	 * of processes of a user
	 */
	public void removingRunningProcesses()
	{
		for(int i =0; i<getUsers().size();i++)
		{
			for(int j=0 ; j<getUsers().get(i).getUserProcesses().size();j++)
			{
				if(getAllProcesses().contains(getUsers().get(i).getUserProcesses().get(j)))
				{
					getUsers().get(i).getUserProcesses().remove(j);	
				}
			}
		}
}
	
	/**
	 * removes the users that have no more processes
	 */
	public void removingEmptyUsers()
	{
		for(int i =0; i<getUsers().size();i++)
		{
			if(getUsers().get(i).getUserProcesses().isEmpty())
			{
				getUsers().remove(i);
						
			}
		}
}

	/**
	 * this method is responsible for running the scheduler
	 */
	public void run()
	{
		if(!getAllProcesses().isEmpty())
		{
			inQuantum = true;
			System.out.println("entered");
			int winner = (int) (Math.random() * (getAllProcesses().size() - 1));
			process running = getAllProcesses().get(winner);
			String n = running.getName();
			
			if (running.getRun_time() > 0)
			{
				System.out.println("process name "
						+ getAllProcesses().get(winner).getName()
						+ " is now running");
				//running one quantum
				getAllProcesses().get(winner).setRun_time(
						running.getRun_time() - 1);
				
				//increasing the clock
				setClk(getClk() + 1);
				System.out.println("clk now is " + getClk());
				
				addingProcesses();
				printList();
				
				if (running.getRun_time() > 0) 
				{
					System.out.println("process name "
							+ getAllProcesses().get(winner).getName()
							+ " is now running");
					
					//running 2nd quantum
					getAllProcesses().get(winner).setRun_time(
							running.getRun_time() - 1);
					//increasing the clk
					setClk(getClk() + 1);
					System.out.println("clk now is " + getClk());
					addingProcesses();
					printList();
				}
				inQuantum = false;
			}
			if(running.getRun_time()==0)
			{
				for(int i=0; i<getAllProcesses().size();i++)
				{
					if (getAllProcesses().get(i).getName().compareTo(n) == 0)
					{
							getAllProcesses().remove(i);
					}
				}
			}
			
			if(getUsers().isEmpty()){
				return;
			}
				run();
		}
		else 
		{
			setClk(getClk()+1);
			System.out.println("clk now is " + getClk());
			inQuantum = false;
			addingProcesses();
		}
		
	}
	
	/**
	 * prints all the process in the program.
	 */
	public void printList()
	{
		for(int i=0; i<getAllProcesses().size() ; i++)
		{
			System.out.println("p is "+ getAllProcesses().get(i).getName() +" ");
		}
	}
	
	//Setters & getters for the attributes of this class
	public int getClk() {
		return clk;
	}

	public void setClk(int clk) {
		this.clk = clk;
	}

	public LinkedList<process> getAllProcesses() {
		return allProcesses;
	}

	public void setAllProcesses(LinkedList<process> allProcesses) {
		this.allProcesses = allProcesses;
	}

	public LinkedList<user> getUsers() {
		return users;
	}

	public void setUsers(LinkedList<user> users) {
		this.users = users;
	}
}
